package org.tamal.classinfo;

import java.io.DataInputStream;
import java.io.IOException;

/**
 * This Class represents inner classes of InnerClasses attribute.
 * @author Tamal Kanti Nath
 *
 */
public final class InnerClass {

    private ClassInfo cls;
    private int innerClassIndex;
    private int outerClassIndex;
    private int innerNameIndex;
    private int accessFlags;

    private InnerClass(DataInputStream in, ClassInfo cls) throws IOException {
        this.cls = cls;
        innerClassIndex = in.readUnsignedShort();
        outerClassIndex = in.readUnsignedShort();
        innerNameIndex = in.readUnsignedShort();
        accessFlags = in.readUnsignedShort();
    }

    /**
     * Returns inner class index.
     * @return the inner class index
     */
    public int getInnerClassIndex() {
        return innerClassIndex;
    }

    /**
     * Returns inner class index.
     * @return the inner class index
     */
    public String getInnerClass() {
        return cls.getPool()[innerClassIndex].toString();
    }

    /**
     * Returns outer class index.
     * @return the outer class index
     */
    public int getOuterClassIndex() {
        return outerClassIndex;
    }

    /**
     * Returns outerClass.
     * @return the outerClass
     */
    public String getOuterClass() {
        return outerClassIndex == 0
                ? null : cls.getPool()[outerClassIndex].toString();
    }

    /**
     * Returns innerName.
     * @return the innerName
     */
    public String getInnerName() {
        return innerNameIndex == 0
                ? null : cls.getPool()[innerNameIndex].toString();
    }

    /**
     * Returns raw access flags.
     * @return the raw access flags
     */
    public int getRawAccessFlags() {
        return accessFlags;
    }

    /**
     * Returns access flags.
     * @return the access flags
     */
    public String getAccessFlags() {
        return AccessFlag.getInnerClassFlag(accessFlags);
    }

    @Override
    public String toString() {
        return getInnerClass();
    }

    /**
     * Reads Inner classes from DataInputStream.
     * @param in the DataInputStream
     * @param cls The ClassInfo reference
     * @return the array of InnerClass
     * @throws IOException exception
     * @see Attribute
     */
    static InnerClass[] readInnerClasses(DataInputStream in, ClassInfo cls)
        throws IOException {
        InnerClass[] classes = new InnerClass[in.readUnsignedShort()];
        for (int i = 0; i < classes.length; ++i) {
            classes[i] = new InnerClass(in, cls);
        }
        return classes;
    }
}
